import { Configuration } from "webpack";
// ‌dotenv  库主要用于环境变量管理‌。它是一个零依赖的模块，用于在Node.js（也适用于其他JavaScript运行环境，如React、Vue项目）中加载环境变量
import * as dotenv from "dotenv";
import HtmlWebpackPlugin from "html-webpack-plugin";
import WebpackBar from "webpackbar";
const webpack = require("webpack");
const path = require("path");

console.log("我的==NODE_ENV", process.env.NODE_ENV);
console.log("我的==BASE_ENV", process.env.BASE_ENV);

// 加载--不同环境的--配置文件
const envConfig = dotenv.config({
  path: path.resolve(__dirname, "../env/.env." + process.env.BASE_ENV),
});

// 样式提取====打包时我们希望把css单独抽离出来,方便配置缓存策略。而插件mini-css-extract-plugin就是来帮我们做这件事的
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const isDev = process.env.NODE_ENV === "development"; // 是否是开发模式

const styleLoadersArray = [
  // MiniCssExtractPlugin.loader,
  "style-loader",
  // isDev ?  : MiniCssExtractPlugin.loader, // 开发环境使用style-looader,打包模式抽离css
  {
    loader: "css-loader",
    options: {
      modules: {
        localIdentName: "[path][name]__[local]--[hash:5]",
      },
    },
  },
];

const baseConfig: Configuration = {
  entry: path.join(__dirname, "../src/index.tsx"), // 入口文件
  // 打包出口文件
  output: {
    filename: "static/js/[name].js", // 每个输出js的名称
    path: path.join(__dirname, "../dist"), // 打包结果输出路径
    clean: true, // webpack4需要配置clean-webpack-plugin来删除dist文件,webpack5内置了
    publicPath: isDev ? "/publicPathTEST/" : "/publicPathPRO/", // 打包后文件的公共前缀路径
    assetModuleFilename: "images/[hash][ext][query]", // ... 这里自定义输出文件名的方式是，将某些资源发送到指定目录
  },
  // loader 配置
  module: {
    rules: [
      // babel-loader 是一个 webpack 的 loader，用于将 ES6+ 的代码转换为向后兼容的 JavaScript 语法，以便在旧版浏览器中运行。
      {
        test: /.(ts|tsx)$/, // 匹配.ts, tsx文件
        exclude: /node_modules/, // 排除node_modules目录，一般第三库都是已经处理好的,不需要再次使用loader去解析
        use: ["thread-loader", "babel-loader"],
      },
      // css-loader 的主要作用是加载和处理 .css 文件，使其成为 webpack 可以理解的模块。在处理过程中，css-loader 会解析 CSS 文件中的 @import 和 url() 等语法，就像 JavaScript 解析 import 或 require() 一样，将其转换为 JavaScript 可以处理的模块
      // style-loader 的作用是将 css-loader 解析后的 CSS 样式插入到 HTML 文档的 <style> 标签中，使样式在浏览器中生效 [
      // {
      //   test: /.css$/, //匹配 css   options: { modules: true }
      //   use: [...styleLoadersArray],
      // },
      {
        test: /\.(le|c)ss$/, //匹配 less |匹配 css  文件
        use: [
          ...styleLoadersArray,
          {
            loader: "less-loader",
            options: {
              lessOptions: {
                modules: true, // 可以加入modules: true，这样就不需要在less文件名加module了
                javascriptEnabled: true, // 如果要在less中写类型js的语法，需要加这一个配置
                globalVars: {
                  PrimaryColor: "#fef6d5", // 全局样式设置
                },
              },
            },
          },
        ],
      },
      {
        test: /\.(png|jpe?g|gif|svg)$/i, // 匹配图片文件
        type: "asset", // type选择asset
        parser: {
          dataUrlCondition: {
            maxSize: 20 * 1024, // 小于10kb转base64
          },
        },
        generator: {
          filename: "static/images/[hash][ext][query]", // 文件输出目录和命名
        },
      },
      {
        test: /.(woff2?|eot|ttf|otf)$/, // 匹配字体图标文件
        type: "asset", // type选择asset
        parser: {
          dataUrlCondition: {
            maxSize: 10 * 1024, // 小于10kb转base64
          },
        },
        generator: {
          filename: "static/fonts/[hash][ext][query]", // 文件输出目录和命名
        },
      },
      {
        test: /.(mp4|webm|ogg|mp3|wav|flac|aac)$/, // 匹配媒体文件
        type: "asset", // type选择asset
        parser: {
          dataUrlCondition: {
            maxSize: 10 * 1024, // 小于10kb转base64
          },
        },
        generator: {
          filename: "static/media/[hash][ext][query]", // 文件输出目录和命名
        },
      },
    ],
  },
  // plugins
  plugins: [
    new MiniCssExtractPlugin({
      filename: "static/css/[name].[contenthash:8].css",
      chunkFilename: "static/css/[name].[contenthash:8].chunk.css",
    }),
    new HtmlWebpackPlugin({
      // 复制 'index.html' 文件，并自动引入打包输出的所有资源（js/css）
      template: path.join(__dirname, "../public/index.html"),
      // 压缩html资源
      // minify: {
      //   collapseWhitespace: true, //去空格
      //   removeComments: true, // 去注释
      // },
    }),
    // 前是打包模式，业务环境是开发环境，这里需要把process.env.BASE_ENV注入到业务代码里面，
    // 就可以通过该环境变量设置对应环境的接口地址和其他数据，
    // 要借助webpack.DefinePlugin插件
    // 注入到业务
    new webpack.DefinePlugin({
      "process.env.BASE_ENV": JSON.stringify(process.env.BASE_ENV),
      "process.env.NODE_ENV": JSON.stringify(process.env.NODE_ENV),
      "process.env": JSON.stringify(envConfig.parsed), // 注入到业务
    }),
    new WebpackBar({
      color: "#85d", // 默认green，进度条颜色支持HEX
      basic: false, // 默认true，启用一个简单的日志报告器
      profile: false, // 默认false，启用探查器。
    }),
  ],
  // 开启持久化存储缓存==改善下一次打包的构建速度,可提速 90% 左右
  cache: {
    type: "filesystem", // 使用文件缓存
  },
  resolve: {
    extensions: [".ts", ".tsx", ".js", ".jsx", ".less", ".css"],
    // 别名需要配置两个地方，这里和 tsconfig.json
    alias: {
      "@": path.join(__dirname, "../src"),
    },
    modules: [path.resolve(__dirname, "../node_modules")], // 查找第三方模块只在本项目的node_modules中查找
  },
};

export default baseConfig;
